package com.cyt.sys.service.impl;

import com.cyt.base.model.dto.ReturnResult;
import com.cyt.base.util.*;
import com.cyt.sys.dao.SysFileDao;
import com.cyt.sys.model.po.SysFile;
import com.cyt.sys.model.vo.SysFileVo;
import com.cyt.sys.service.SysFileService;
import com.cyt.sys.util.FilePathUtil;
import com.cyt.sys.util.SysDictCode;
// import com.cyt.sys.util.ToPDF;
import com.github.pagehelper.StringUtil;
import org.apache.commons.collections.map.HashedMap;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import sun.misc.BASE64Decoder;
import tk.mybatis.mapper.entity.Example;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Properties;

/**
 *@Author: YuShengQiang
 *@Date: 2018-12-04 10:34
 *@Description:基础附件service实现类
 */
@Service("sysFileService")
public class SysFileServiceImpl extends BaseServiceImpl<SysFile> implements SysFileService {
    @Resource
    private SysFileDao sysFileDao;

    private Properties prop = new Properties();

    private static String PDFCONVERSION_FAIL_MSG = "PFD转换失败";


    @Autowired
    public void setBaseDao(SysFileDao sysFileDao) {
        this.baseDao = sysFileDao;
    }


    /**
     * @param file     文件对象
     * @param request  请求
     * @param catalog  文件保存自定义目录
     * @param objectId 文件保存objectId，空为自定义
     * @param memId 当前登录用户信息
     * @return
     * @Author: YuShengQiang
     * @Date: 2018-12-04 10:40
     * @Description:单个图片上传
     */
    @Override
    public ReturnResult singleImage(MultipartFile file, HttpServletRequest request, String catalog, String objectId, String memId ) {
        return fileUpload(file, request, catalog, BaseConstant.FILE_TYPE_IMAGE, objectId, memId);
    }


    /**
     * @param file     文件对象
     * @param request  请求
     * @param catalog  文件保存自定义目录
     * @param objectId 文件保存objectId，空为自定义
     * @param memId 当前登录用户信息
     * @return
     * @Author: YuShengQiang
     * @Date: 2018-12-04 10:40
     * @Description:单个附件上传
     */
    @Override
    public ReturnResult singleFile(MultipartFile file, HttpServletRequest request, String catalog, String objectId,  String memId) {
        return fileUpload(file, request, catalog, "", objectId, memId);
    }

    /**
     * @param file     文件对象
     * @param request  请求
     * @param catalog  文件保存自定义目录
     * @param objectId 文件保存objectId，空为自定义
     * @param memId 当前登录用户信息
     * @return
     * @Author: YuShengQiang
     * @Date: 2018-12-04 10:40
     * @Description:文本编辑器附件上传
     */
    @Override
    public ReturnResult layEditUpload(MultipartFile file, HttpServletRequest request, String catalog, String objectId, String memId) {
        ReturnResult returnResult = fileUpload(file, request, catalog, "", objectId, memId);
        if (returnResult.getCode() == ErrorCode.CODE_0) {
            Map<String, String> data = new HashedMap();
            data.put("src", ("/sysFile/showFileByPath?path="+((SysFile) returnResult.getData()).getPath()));
            data.put("title", ((SysFile) returnResult.getData()).getFileName());
            return new ReturnResult(data);
        }
        return returnResult;
    }

    /**
     * @param objectId 文件保存objectId，空为自定义
     * @return
     * @Author: YuShengQiang
     * @Date: 2018-12-04 10:40
     * @Description:根据objectId删除附件
     */
    @Override
    public ReturnResult deleteByobjectId(String objectId) {
        sysFileDao.deleteByobjectId(new SysFile(objectId, DictCode.BASE_REMOVE_TAG_DELETE));
        return new ReturnResult();
    }

    /**
     * @param id 主键
     * @return
     * @Author: YuShengQiang
     * @Date: 2018-12-04 10:40
     * @Description:根据id删除附件
     */
    @Override
    public ReturnResult deleteById(HttpServletRequest request, String id) {
        SysFile sysFile = this.selectByPrimaryKey(id);
        if (sysFile != null) {
            FilePathUtil.deleteFile(request, sysFile.getPath());
            sysFileDao.deleteByPrimaryKey(id);
        }
        return new ReturnResult();
    }

    /**
     * @param sysFileVo 对象
     * @Author: YuShengQiang
     * @Date: 2018-12-05 14:58
     * @Description:
     */
    @Override
    public ReturnResult list(SysFileVo sysFileVo) {
        return new ReturnResult(listExample(sysFileVo));
    }
    /**
     * 根据附件objectId预览/下载第一个附件
     *
     * @param objectId 附件objectId
     * @return
     * @author shengQiang yu
     * @date 2019-06-26 16:36
     */
    @Override
    public void showFileByObjectId(HttpServletResponse response,HttpServletRequest request,String objectId) throws IOException {
        List<SysFile> sysFileList=listExample(new SysFileVo(objectId));
        if(sysFileList!=null&&sysFileList.size()>0){
            //存储方式 1、本地存储，2、网盘存储，3、自定义配置
            if(SysDictCode.SYS_STORAGE_TYPE_WPCC.equals(sysFileList.get(0).getStorageType())){
                //网盘存储，展示不做
            }else{
                showFileByPath(response,request,sysFileList.get(0).getPath());
            }
        }
    }
    /**
     * 根据附件id预览/下载附件
     *
     * @param fileId 附件id
     * @return
     * @author shengQiang yu
     * @date 2019-06-26 16:36
     */
    @Override
    public void showFileById(HttpServletResponse response,HttpServletRequest request,String fileId) throws IOException {
       SysFile sysFile=selectByPrimaryKey(fileId);
       if(sysFile!=null){
           //存储方式 1、本地存储，2、网盘存储，3、自定义配置
           if(SysDictCode.SYS_STORAGE_TYPE_WPCC.equals(sysFile.getStorageType())){
                //网盘存储，展示不做
           }else{
               showFileByPath(response,request,sysFile.getPath());
           }
       }
    }
    /**
     * 根据路径预览/下载附件
     *
     * @param path 附件路径
     * @return
     * @author shengQiang yu
     * @date 2019-06-26 16:36
     */
    @Override
    public void showFileByPath(HttpServletResponse response,HttpServletRequest request,String path) throws IOException {
        String realPath = FilePathUtil.acceptCheckRealPath(request);
        File file = new File(realPath+path);
        if(!file.exists()){
            return;
        }
        OutputStream os = response.getOutputStream();
        FileInputStream fips = new FileInputStream(file);
        ByteArrayOutputStream bops = new ByteArrayOutputStream();
        int data = -1;
        while ((data = fips.read()) != -1) {
            bops.write(data);
        }
        byte[] btImg = bops.toByteArray();
        os.write(btImg);
        os.flush();
    }

    /**
     * 附件下载
     *
     * @param id       附件id
     * @param response HttpServletResponse对象
     * @param request  HttpServletRequest对象
     * @return
     * @author shengQiang yu
     * @date 2019-03-07 17:10
     */
    @Override
    public void download(HttpServletResponse response, HttpServletRequest request, String id) {
        SysFile sysFile = sysFileDao.selectByPrimaryKey(id);
        if (sysFile != null) {
            OutputStream outputStream = null;
            FileInputStream inputStream = null;
            try {
                response.setContentType("application/force-download");// 设置强制下载不打开
                String filenamereal = sysFile.getFileName();
                response.addHeader("Content-Disposition", "attachment;fileName=" + URLEncoder.encode(filenamereal, "utf-8"));
                outputStream = response.getOutputStream();
                String storeType = sysFile.getStorageType();
                //本地服务器存储类型
                String path = sysFile.getPath();
                String fileName = sysFile.getFileName();

                String realPath =FilePathUtil.acceptCheckRealPath(request);

                String absoluteAdress = realPath + path;
                inputStream = new FileInputStream(absoluteAdress);
                byte[] buffer = new byte[1024];
                int len = -1;
                StringBuffer sb = new StringBuffer();
                while ((len = inputStream.read(buffer)) != -1) {
                    outputStream.write(buffer, 0, len);
                }
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                try {
                    if (outputStream != null) {
                        outputStream.close();
                    }
                    if (inputStream != null) {
                        outputStream.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * @param sysFileVo
     * @return
     * @Author: YuShengQiang
     * @Date: 2018-12-05 14:58
     * @Description: 查询对象集合
     */
    @Override
    public List<SysFile> listExample(SysFileVo sysFileVo) {
        Example example = new Example(SysFile.class);
        Example.Criteria criteria = example.createCriteria();
        example.setOrderByClause("create_time desc");
        if (StringUtil.isNotEmpty(sysFileVo.getObjectId())) {
            criteria.andEqualTo("objectId", sysFileVo.getObjectId());
        }
        if (StringUtil.isNotEmpty(sysFileVo.getFileName())) {
            criteria.andLike("fileName", sysFileVo.getFileName());
        }
        criteria.andEqualTo("removeTag", BaseConstant.REMOVE_TAG_NO);
        List<SysFile> list = sysFileDao.selectByExample(example);
        return list;
    }


    /**
     * @param file            文件对象
     * @param request         请求
     * @param catalog         文件保存自定义目录
     * @param objectId        文件保存objectId，空为自定义
     * @param requestFileType 文件要求类型：1、图片 ，空为不做要求
     * @param  memId      当前登录用户信息
     * @return
     * @Author: YuShengQiang
     * @Date: 2018-12-04 10:40
     * @Description:附件上传
     */
    public ReturnResult fileUpload(MultipartFile file, HttpServletRequest request, String catalog, String requestFileType, String objectId, String memId) {
        ReturnResult returnResult = fileUpload(file, request, catalog, requestFileType);
        if (ErrorCode.CODE_0 == returnResult.getCode()) {
            // 文件原名称
            String fileName = file.getOriginalFilename();
            //文件类型
            String type = BaseUtil.acceptFileType(fileName);
            SysFile sysFile = new SysFile();
            sysFile.setId(BaseUtil.uId());
            sysFile.setFileName(fileName);
            sysFile.setFileSize(file.getSize());
            sysFile.setExtendName(type);
            sysFile.setObjectId(StringUtils.isNotEmpty(objectId) ? objectId : BaseUtil.uId());
            sysFile.setStorageType(DictCode.STORAGE_TYPE_LOCALHOST);
            sysFile.setPath(returnResult.getData().toString());
            sysFile.setType(catalog);
            sysFile.setCreatorId(memId);
            sysFile.setRemoveTag(DictCode.BASE_REMOVE_TAG_NORMAL);
            sysFile.setCreateTime(new Date());
            //插入到数据库
            int id = sysFileDao.insert(sysFile);
            if (id > 0) {
                return new ReturnResult(sysFile);
            } else {
                return new ReturnResult(ErrorCode.CODE_106, ErrorCode.CODE_106_MSG);
            }
        } else {
            return returnResult;
        }

    }
    /**
     * @param imgBase64URL    图片Base64字符串
     * @param request         请求
     * @param catalog         文件保存自定义目录
     * @param objectId        文件保存objectId，空为自定义
     * @param fileType      图片类型如：png,jpg等
     * @param  memId      当前登录用户信息
     * @return
     * @Author: YuShengQiang
     * @Date: 2018-12-04 10:40
     * @Description:图片Base64上传
     */
    @Override
    public ReturnResult imageBase64Upload(String imgBase64URL, HttpServletRequest request, String catalog, String fileType, String objectId, String memId) {
        ReturnResult returnResult = imageBase64Upload(imgBase64URL, request, catalog, fileType);
        if (ErrorCode.CODE_0 == returnResult.getCode()) {
            //文件类型
            SysFile sysFile = new SysFile();
            sysFile.setId(BaseUtil.uId());
            sysFile.setExtendName(fileType);
            sysFile.setObjectId(StringUtils.isNotEmpty(objectId) ? objectId : BaseUtil.uId());
            sysFile.setStorageType(DictCode.STORAGE_TYPE_LOCALHOST);
            sysFile.setPath(returnResult.getData().toString());
            sysFile.setType(catalog);
            sysFile.setCreatorId(memId);
            sysFile.setRemoveTag(DictCode.BASE_REMOVE_TAG_NORMAL);
            sysFile.setCreateTime(new Date());
            //插入到数据库
            int id = sysFileDao.insert(sysFile);
            if (id > 0) {
                return new ReturnResult(sysFile);
            } else {
                return new ReturnResult(ErrorCode.CODE_106, ErrorCode.CODE_106_MSG);
            }
        } else {
            return returnResult;
        }

    }
    /**
     * @param imgBase64URL    图片Base64字符串
     * @param request         请求
     * @param catalog         文件保存自定义目录
     * @param fileType      图片类型如：png,jpg等
     * @return
     * @Author: YuShengQiang
     * @Date: 2018-12-04 10:40
     * @Description:图片Base64上传
     */
    @Override
    public ReturnResult imageBase64Upload(String imgBase64URL, HttpServletRequest request, String catalog, String fileType) {
        if (!BaseUtil.fileCheckImg(fileType)) {
            return new ReturnResult(ErrorCode.CODE_105, ErrorCode.CODE_105_MSG);
        }
        // 项目在容器中实际发布运行的根路径
        String realPath = FilePathUtil.acceptCheckRealPath(request);
        // 自定义的文件名称
        String newFileName = BaseUtil.acceptFileName(fileType);
        // 相对目录
        String realDir = "upload";
        if (StringUtils.isNotEmpty(catalog)) {
            realDir += "/" + catalog.trim();
        }
        //获取目录
        String dir = BaseUtil.acceptFileDir(realPath, realDir);
        // 转存文件到指定的路径
        BASE64Decoder decoder = new BASE64Decoder();
        try {
            // Base64解码
            byte[] b = decoder.decodeBuffer(imgBase64URL);
            for (int i = 0; i < b.length; ++i) {
                if (b[i] < 0) {// 调整异常数据
                    b[i] += 256;
                }
            }
            OutputStream out = new FileOutputStream(dir+"/"+newFileName);
            out.write(b);
            out.flush();
            out.close();
        } catch (Exception e) {
            return new ReturnResult(ErrorCode.CODE_106, ErrorCode.CODE_106_MSG);
        }
        return new ReturnResult("/" + realDir + "/" + newFileName);

    }
    /**
     * @param file            文件对象
     * @param request         请求
     * @param catalog         文件保存自定义目录
     * @param requestFileType 文件要求类型：1、图片 ，空为不做要求
     * @return
     * @Author: YuShengQiang
     * @Date: 2018-12-04 10:40
     * @Description:附件上传
     */
    @Override
    public ReturnResult fileUpload(MultipartFile file, HttpServletRequest request, String catalog, String requestFileType) {
        // 文件原名称
        String fileName = file.getOriginalFilename();
        //文件类型
        String type = BaseUtil.acceptFileType(fileName);
        //判断是否有文件类型要求
        if (StringUtil.isNotEmpty(requestFileType)) {
            if (BaseConstant.FILE_TYPE_IMAGE.equals(requestFileType)) {
                //图片文件
                if (!BaseUtil.fileCheckImg(type)) {
                    return new ReturnResult(ErrorCode.CODE_105, ErrorCode.CODE_105_MSG);
                }
            } else if (BaseConstant.FILE_TYPE_EXECL.equals(requestFileType)) {
                //文档文件
                if (!BaseUtil.fileCheckExecl(type)) {
                    return new ReturnResult(ErrorCode.CODE_105, ErrorCode.CODE_105_MSG);
                }
            }
        }

        // 项目在容器中实际发布运行的根路径
        String realPath = FilePathUtil.acceptCheckRealPath(request);
        // 自定义的文件名称
        String newFileName = BaseUtil.acceptFileName(type);
        // 相对目录
        String realDir = "upload";
        if (StringUtils.isNotEmpty(catalog)) {
            realDir += "/" + catalog.trim();
        }
        //获取目录
        String dir = BaseUtil.acceptFileDir(realPath, realDir);
        // 转存文件到指定的路径
        try {
            file.transferTo(new File(dir, newFileName));
        } catch (IOException e) {
            return new ReturnResult(ErrorCode.CODE_106, ErrorCode.CODE_106_MSG);
        }
        return new ReturnResult("/" + realDir + "/" + newFileName);

    }


    /**
     * @Author: sunli
     * @Date: 2018-12-04 10:40
     * @param request 请求
     * @param id 附件id
     * @Description:office转换pdf
     *
     */
    @Override
    public ReturnResult conversionFile(HttpServletRequest request, String id) {

        //ToPDF pdf = new ToPDF();
        SysFile sysFile = sysFileDao.selectByPrimaryKey(id);
        String path = sysFile.getPath();
        String absoluteAdress = FilePathUtil.acceptRealPath(request) + path;
        int splitIndex=sysFile.getFileName().lastIndexOf(".");
        String Name=sysFile.getFileName().substring(0,splitIndex);
        String savePdfAddress = ProProperties.getInstance().addressOfPdf();
        String pdfOfFile=savePdfAddress+File.separator +sysFile.getObjectId();
        File file=new File(pdfOfFile);
        //创建输出路径
        if  (!file .exists()  && !file .isDirectory())
        {
            file .mkdir();
        }

        String outFilePath=savePdfAddress+File.separator +sysFile.getObjectId()+File.separator  +Name+".pdf";
        //调用office转pdf方法
        //boolean  status=pdf.toPDF(absoluteAdress,outFilePath);
        return new ReturnResult(outFilePath);
        /*if(status){
            return new ReturnResult(outFilePath);
        }else{
            return new ReturnResult(ErrorCode.CODE_800, ErrorCode.CODE_800_MSG);
        }*/
    }

    /**
     * 根据条件获取单个附件信息
     *
     * @param sysFileVo 参数传入对象
     * @return SysFile
     * @author rong yuan
     * @date 2019/8/12 10:41
     */
    @Override
    public SysFile selectOneByExample(SysFileVo sysFileVo) {
        Example example = new Example(SysFile.class);
        Example.Criteria criteria = example.createCriteria();
        if (StringUtils.isNotBlank(sysFileVo.getObjectId())) {
            criteria.andEqualTo("objectId", sysFileVo.getObjectId());
        }
        criteria.andEqualTo("removeTag", BaseConstant.REMOVE_TAG_NO);
        return sysFileDao.selectOneByExample(example);
    }
}